#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define LINE_SIZE 1024
#define ARGC_SIZE 32
#define DELIM " \t"
#define EXIT_CODE 36
#define ENV_ROW 128
#define ENV_COL 128

int row = 0;
char commandline[LINE_SIZE];
char pwd[LINE_SIZE];
int quit = 0;
char* argv[ARGC_SIZE];
int lastcode = 0;
char myenv[ENV_ROW][ENV_COL];


const char* getusername()
{
    return getenv("USER");
}

const char* gethostname()
{
    return getenv("HOSTNAME");
}

void getpwd()
{
    getcwd(pwd, sizeof(pwd));
}


void interAct(char* cline, int size)
{
    getpwd();
    printf(LEFT"%s@%s %s"RIGHT""LABLE" ", getusername(), gethostname(), pwd );
    char* s = fgets(cline, size, stdin);
    (void)s;
    
    cline[strlen(cline)-1] = '\0';
}

int splitString(char cline[], char* _argv[])
{
    int i = 0;
    _argv[i++] = strtok(cline, DELIM);
    while(_argv[i++] = strtok(NULL, DELIM));
    return i - 1;
}

int buildCommand(char* _argv[], int _argc)
{
    if(_argc == 2 && strcmp(_argv[0], "cd") == 0)
    {
        chdir(_argv[1]);
        getpwd();
        sprintf(getenv("PWD"), "%s", pwd);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "export") == 0)
    {
        strcpy(myenv[row], _argv[1]);
        putenv(myenv[row]);
        row++;
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "echo") == 0)
    {
        if(strcmp(_argv[1], "$?") == 0)
        {
            printf("%d\n", lastcode);
            lastcode = 0;
        }
        else if(*_argv[1] == '$')
        {
            char* val = getenv(_argv[1] + 1);
            if(val)
                printf("%s\n", val);
        }
        else 
        {
            printf("%s\n", _argv[1]);
        }
        return 1;
    }
    
    // ls 做特殊处理，添加颜色
    if(strcmp(_argv[0], "ls") == 0)
    {
        _argv[_argc++] = "--color";
        _argv[_argc] = NULL;
    }
    return 0;
}

void normalExcute(char* _argv[])
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return;
    }
    else if(id == 0)
    {
        // 子进程执行请求
        execvp(_argv[0], _argv);
        exit(EXIT_CODE);
    }
    else 
    {
        // 父进程等待
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if(rid == id)
        {
            // 最后一次进程执行状态码
            lastcode = WEXITSTATUS(status);
        }
    }   
}


int main()
{
    while(!quit)
    {
        // 1、命令行交互
        interAct(commandline, sizeof(commandline));

        // 2、字符串分割，解析命令行
        int argc = splitString(commandline, argv);
        if(argc == 0)
            continue;
        
        // debug
        //for(int i=0;i<argv[i];i++)
        //    printf("[%d] : %s\n", i, argv[i]);

        // 3、指令判断
        int n = buildCommand(argv, argc);
        
        // 4、普通指令执行
        if(!n)
            normalExcute(argv);
    }

    return 0;
}
